package top.jiangqiang.qyblog.core.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import com.github.yulichang.wrapper.DeleteJoinWrapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.springframework.stereotype.Service;
import top.jiangqiang.qyblog.common.base.query.PageResult;
import top.jiangqiang.qyblog.common.base.response.Result;
import top.jiangqiang.qyblog.common.exception.JsonException;
import top.jiangqiang.qyblog.core.base.service.impl.BaseServiceImpl;
import top.jiangqiang.qyblog.core.domain.dto.BlogTagAddDto;
import top.jiangqiang.qyblog.core.domain.dto.BlogTagUpdateDto;
import top.jiangqiang.qyblog.core.domain.dto.TagQueryDto;
import top.jiangqiang.qyblog.core.domain.entity.ArticleTag;
import top.jiangqiang.qyblog.core.domain.entity.BlogTag;
import top.jiangqiang.qyblog.core.domain.vo.BlogTagVo;
import top.jiangqiang.qyblog.core.mapper.TagMapper;
import top.jiangqiang.qyblog.core.service.ITagService;

import java.util.List;

/**
 * <p>
 * 文章标签 服务实现类
 * </p>
 *
 * @author JiangQiang
 * @since 2023-05-29
 */
@Service
public class TagServiceImpl extends BaseServiceImpl<TagMapper, BlogTag> implements ITagService {

    @Override
    public Result<PageResult<BlogTagVo>> findByCondition(TagQueryDto tagQueryDto) {
        PageResult<BlogTagVo> page = getBlogTagMPJLambdaWrapper()
                .like(StrUtil.isNotBlank(tagQueryDto.getName()), BlogTag::getName, tagQueryDto.getName())
                .page(tagQueryDto.toPage(), BlogTagVo.class);
        return Result.ok(page);
    }

    /**
     * 构造查询片段，查询标签相关属性以及该标签下文章数量
     *
     * @return
     */
    private MPJLambdaWrapper<BlogTag> getBlogTagMPJLambdaWrapper() {
        return lambdaJoinWrapper()
                .selectAll(BlogTag.class)
                .selectSub(ArticleTag.class,
                        wrapper -> wrapper.selectCount(ArticleTag::getId).eq(ArticleTag::getTagId, BlogTag::getId),
                        BlogTagVo::getArticleCount);
    }

    @Override
    public Result<BlogTagVo> saveTag(BlogTagAddDto tagAddDto) {
        String name = tagAddDto.getName();
        BlogTag blogTag = lambdaQuery().eq(BlogTag::getName, name).one();
        if (blogTag != null) {
            throw new JsonException("标签名称不允许重复");
        }
        String alias = tagAddDto.getAlias();
        if (StrUtil.isNotBlank(alias)) {
            //别名不为空
            blogTag = lambdaQuery().eq(BlogTag::getAlias, alias).one();
            if (blogTag != null) {
                throw new JsonException("标签别名不允许重复");
            }
            blogTag = typeConverter.convert(tagAddDto, BlogTag.class);
            baseMapper.insert(blogTag);
            return getTag(blogTag.getId());
        } else {
            Long tagId = saveTag(name);
            return getTag(tagId);
        }
    }

    @Override
    public Long saveTag(String tagName) {
        //别名为空，生成不重复的别名
        String alias = PinyinUtil.getPinyin(tagName, "-");
        //likeRight 查询别名 获取所有以alias为开头的别名
        List<BlogTag> blogTagList = lambdaQuery().likeRight(BlogTag::getAlias, alias).list();
        if (CollUtil.isNotEmpty(blogTagList)) {
            List<String> aliasList = blogTagList.stream().map(BlogTag::getAlias).toList();
            String tmpAlias = alias;
            while (aliasList.contains(tmpAlias)) {
                tmpAlias = alias + RandomUtil.randomNumbers(5);
            }
            alias = tmpAlias;
        }
        BlogTag blogTag = new BlogTag();
        blogTag.setName(tagName);
        blogTag.setAlias(alias);
        baseMapper.insert(blogTag);
        return blogTag.getId();
    }


    @Override
    public Result<BlogTagVo> editTag(BlogTagUpdateDto tagUpdateDto) {
        Long tagId = tagUpdateDto.getId();
        if (getById(tagId) == null) {
            throw new JsonException("标签不存在");
        }
        String name = tagUpdateDto.getName();
        BlogTag blogTag = lambdaQuery().eq(BlogTag::getName, name).one();
        if (blogTag != null && !blogTag.getId().equals(tagId)) {
            throw new JsonException("标签名称不允许重复");
        }
        String alias = tagUpdateDto.getAlias();
        //根据别名查询标签对象
        blogTag = lambdaQuery().eq(BlogTag::getAlias, alias).one();
        //标签存在，并且和当前文章的id不一致 表示即将修改的别名已经存在
        if (blogTag != null && !blogTag.getId().equals(tagId)) {
            throw new JsonException("标签别名重复");
        }
        blogTag = typeConverter.convert(tagUpdateDto, BlogTag.class);
        baseMapper.updateById(blogTag);
        return getTag(tagId);
    }

    @Override
    public Boolean deleteTag(Long id) {
        DeleteJoinWrapper<BlogTag> deleteJoinWrapper = deleteJoinWrapper().deleteAll()
                .leftJoin(ArticleTag.class, ArticleTag::getTagId, BlogTag::getId)
                .eq(BlogTag::getId, id);
        return deleteJoin(deleteJoinWrapper);
    }

    @Override
    public Result<BlogTagVo> getTag(Long id) {
        BlogTagVo tagVo = getBlogTagMPJLambdaWrapper().eq(BlogTag::getId, id).one(BlogTagVo.class);
        if (tagVo == null) {
            return Result.error("标签不存在");
        } else {
            return Result.ok(tagVo);
        }
    }

    @Override
    public BlogTagVo getTagByTagName(String tagName) {
        return getBlogTagMPJLambdaWrapper().eq(BlogTag::getName, tagName).one(BlogTagVo.class);
    }
}
